home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 21 / CU Amiga Magazine's Super CD-ROM 21 (1998)(EMAP Images)(GB)[!][issue 1998-04].iso / CUCD / Games / ADoom / ADoom_src / r_draw.c < prev    next >
C/C++ Source or Header  |  1998-01-31  |  24KB  |  1,075 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    The actual span/column drawing functions.
  21. //    Here find the main potential for optimization,
  22. //     e.g. inline assembly, different algorithms.
  23. //
  24. //-----------------------------------------------------------------------------
  25.  
  26.  
  27. static const char
  28. rcsid[] = "$Id: r_draw.c,v 1.4 1997/02/03 16:47:55 b1 Exp $";
  29.  
  30.  
  31. #include "doomdef.h"
  32.  
  33. #include "i_system.h"
  34. #include "z_zone.h"
  35. #include "w_wad.h"
  36.  
  37. #include "r_local.h"
  38.  
  39. // Needs access to LFB (guess what).
  40. #include "v_video.h"
  41.  
  42. // State.
  43. #include "doomstat.h"
  44.  
  45.  
  46. // ?
  47. #define MAXWIDTH            1120
  48. #define MAXHEIGHT            832
  49.  
  50. // status bar height at bottom of screen
  51. #define SBARHEIGHT        32
  52.  
  53. //
  54. // All drawing to the view buffer is accomplished in this file.
  55. // The other refresh files only know about ccordinates,
  56. //  not the architecture of the frame buffer.
  57. // Conveniently, the frame buffer is a linear one,
  58. //  and we need only the base address,
  59. //  and the total size == width*height*depth/8.,
  60. //
  61.  
  62.  
  63. byte*        viewimage; 
  64. int        viewwidth;
  65. int        scaledviewwidth;
  66. int        viewheight;
  67. int        viewwindowx;
  68. int        viewwindowy; 
  69. byte*        ylookup[MAXHEIGHT]; 
  70. byte*        ylookup2[MAXHEIGHT]; 
  71. int        columnofs[MAXWIDTH]; 
  72.  
  73. // Color tables for different players,
  74. //  translate a limited part to another
  75. //  (color ramps used for  suit colors).
  76. //
  77. FAR byte    translations[3][256];    
  78.  
  79.  
  80.  
  81.  
  82. //
  83. // R_DrawColumn
  84. // Source is the top of the column to scale.
  85. //
  86. lighttable_t*        dc_colormap; 
  87. int            dc_x; 
  88. int            dc_yl; 
  89. int            dc_yh; 
  90. fixed_t            dc_iscale; 
  91. fixed_t            dc_texturemid;
  92.  
  93. // first pixel in a column (possibly virtual) 
  94. byte*            dc_source;        
  95.  
  96. // just for profiling 
  97. int            dccount;
  98.  
  99. //
  100. // A column is a vertical slice/span from a wall texture that,
  101. //  given the DOOM style restrictions on the view orientation,
  102. //  will always have constant z depth.
  103. // Thus a special case loop for very fast rendering can
  104. //  be used. It has also been used with Wolfenstein 3D.
  105. // 
  106. // UNUSED.
  107. #ifndef AMIGA
  108. void R_DrawColumn (void) 
  109.     int            count; 
  110.     byte*        dest; 
  111.     fixed_t        frac;
  112.     fixed_t        fracstep;     
  113.  
  114.     count = dc_yh - dc_yl; 
  115.  
  116.     // Zero length, column does not exceed a pixel.
  117.     if (count < 0) 
  118.     return; 
  119.                  
  120. #ifdef RANGECHECK 
  121.     if ((unsigned)dc_x >= SCREENWIDTH
  122.     || dc_yl < 0
  123.     || dc_yh >= SCREENHEIGHT) 
  124.     I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); 
  125. #endif 
  126.  
  127.     // Framebuffer destination address.
  128.     // Use ylookup LUT to avoid multiply with ScreenWidth.
  129.     // Use columnofs LUT for subwindows? 
  130.     dest = ylookup[dc_yl] + columnofs[dc_x];  
  131.  
  132.     // Determine scaling,
  133.     //  which is the only mapping to be done.
  134.     fracstep = dc_iscale; 
  135.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  136.  
  137.     // Inner loop that does the actual texture mapping,
  138.     //  e.g. a DDA-lile scaling.
  139.     // This is as fast as it gets.
  140.     do 
  141.     {
  142.     // Re-map color indices from wall texture column
  143.     //  using a lighting/special effects LUT.
  144.     *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
  145.     
  146.     dest += SCREENWIDTH; 
  147.     frac += fracstep;
  148.     
  149.     } while (count--); 
  150. #endif
  151.  
  152.  
  153.  
  154. // UNUSED.
  155. // Loop unrolled.
  156. #if 0
  157. void R_DrawColumn (void) 
  158.     int            count; 
  159.     byte*        source;
  160.     byte*        dest;
  161.     byte*        colormap;
  162.     
  163.     unsigned        frac;
  164.     unsigned        fracstep;
  165.     unsigned        fracstep2;
  166.     unsigned        fracstep3;
  167.     unsigned        fracstep4;     
  168.  
  169.     count = dc_yh - dc_yl + 1; 
  170.  
  171.     source = dc_source;
  172.     colormap = dc_colormap;         
  173.     dest = ylookup[dc_yl] + columnofs[dc_x];  
  174.      
  175.     fracstep = dc_iscale<<9; 
  176.     frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9; 
  177.  
  178.     fracstep2 = fracstep+fracstep;
  179.     fracstep3 = fracstep2+fracstep;
  180.     fracstep4 = fracstep3+fracstep;
  181.     
  182.     while (count >= 8) 
  183.     { 
  184.     dest[0] = colormap[source[frac>>25]]; 
  185.     dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]]; 
  186.     dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]]; 
  187.     dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]];
  188.     
  189.     frac += fracstep4; 
  190.  
  191.     dest[SCREENWIDTH*4] = colormap[source[frac>>25]]; 
  192.     dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]]; 
  193.     dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]]; 
  194.     dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]]; 
  195.  
  196.     frac += fracstep4; 
  197.     dest += SCREENWIDTH*8; 
  198.     count -= 8;
  199.     } 
  200.     
  201.     while (count > 0)
  202.     { 
  203.     *dest = colormap[source[frac>>25]]; 
  204.     dest += SCREENWIDTH; 
  205.     frac += fracstep; 
  206.     count--;
  207.     } 
  208. }
  209. #endif
  210.  
  211.  
  212. #ifndef AMIGA
  213. void R_DrawColumnLow (void) 
  214.     int            count; 
  215.     byte*        dest; 
  216.     byte*        dest2;
  217.     fixed_t        frac;
  218.     fixed_t        fracstep;     
  219.  
  220.     count = dc_yh - dc_yl; 
  221.  
  222.     // Zero length.
  223.     if (count < 0) 
  224.     return; 
  225.                  
  226. #ifdef RANGECHECK 
  227.     if ((unsigned)dc_x >= SCREENWIDTH
  228.     || dc_yl < 0
  229.     || dc_yh >= SCREENHEIGHT)
  230.     {
  231.     
  232.     I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
  233.     }
  234.     //    dccount++; 
  235. #endif 
  236.     // Blocky mode, need to multiply by 2.
  237.     dc_x <<= 1;
  238.     
  239.     dest = ylookup[dc_yl] + columnofs[dc_x];
  240.     dest2 = ylookup[dc_yl] + columnofs[dc_x+1];
  241.     
  242.     fracstep = dc_iscale; 
  243.     frac = dc_texturemid + (dc_yl-centery)*fracstep;
  244.     
  245.     do 
  246.     {
  247.     // Hack. Does not work corretly.
  248.     *dest2 = *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
  249.     dest += SCREENWIDTH;
  250.     dest2 += SCREENWIDTH;
  251.     frac += fracstep; 
  252.  
  253.     } while (count--);
  254. }
  255. #endif
  256.  
  257.  
  258. //
  259. // Spectre/Invisibility.
  260. //
  261. #ifndef AMIGA
  262. #define FUZZTABLE       50 
  263. #else
  264. #define FUZZTABLE       250
  265. #endif
  266. #define FUZZOFF    (SCREENWIDTH)
  267.  
  268.  
  269. int    fuzzoffset[FUZZTABLE] =
  270. {
  271.     FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  272.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  273.     FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,
  274.     FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  275.     FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,
  276.     FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,
  277.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF 
  278. #ifdef AMIGA
  279.     ,FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  280.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  281.     FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,
  282.     FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  283.     FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,
  284.     FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,
  285.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,
  286.     FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  287.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  288.     FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,
  289.     FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  290.     FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,
  291.     FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,
  292.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,
  293.     FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  294.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  295.     FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,
  296.     FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  297.     FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,
  298.     FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,
  299.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,
  300.     FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  301.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  302.     FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,
  303.     FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  304.     FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,
  305.     FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,
  306.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF
  307. #endif
  308. }; 
  309.  
  310.  
  311. int    fuzzpos = 0; 
  312.  
  313.  
  314. #ifndef AMIGA
  315.  
  316. //
  317. // Framebuffer postprocessing.
  318. // Creates a fuzzy image by copying pixels
  319. //  from adjacent ones to left and right.
  320. // Used with an all black colormap, this
  321. //  could create the SHADOW effect,
  322. //  i.e. spectres and invisible players.
  323. //
  324. void R_DrawFuzzColumn (void) 
  325.     int            count; 
  326.     byte*        dest; 
  327.     fixed_t        frac;
  328.     fixed_t        fracstep;     
  329.  
  330.     // Adjust borders. Low... 
  331.     if (!dc_yl) 
  332.     dc_yl = 1;
  333.  
  334.     // .. and high.
  335.     if (dc_yh == viewheight-1) 
  336.     dc_yh = viewheight - 2; 
  337.          
  338.     count = dc_yh - dc_yl; 
  339.  
  340.     // Zero length.
  341.     if (count < 0) 
  342.     return; 
  343.  
  344.     
  345. #ifdef RANGECHECK 
  346.     if ((unsigned)dc_x >= SCREENWIDTH
  347.     || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
  348.     {
  349.     I_Error ("R_DrawFuzzColumn: %i to %i at %i",
  350.          dc_yl, dc_yh, dc_x);
  351.     }
  352. #endif
  353.  
  354.  
  355.     // Keep till detailshift bug in blocky mode fixed,
  356.     //  or blocky mode removed.
  357.     /* WATCOM code 
  358.     if (detailshift)
  359.     {
  360.     if (dc_x & 1)
  361.     {
  362.         outpw (GC_INDEX,GC_READMAP+(2<<8) ); 
  363.         outp (SC_INDEX+1,12); 
  364.     }
  365.     else
  366.     {
  367.         outpw (GC_INDEX,GC_READMAP); 
  368.         outp (SC_INDEX+1,3); 
  369.     }
  370.     dest = destview + dc_yl*80 + (dc_x>>1); 
  371.     }
  372.     else
  373.     {
  374.     outpw (GC_INDEX,GC_READMAP+((dc_x&3)<<8) ); 
  375.     outp (SC_INDEX+1,1<<(dc_x&3)); 
  376.     dest = destview + dc_yl*80 + (dc_x>>2); 
  377.     }*/
  378.  
  379.     
  380.     // Does not work with blocky mode.
  381.     dest = ylookup[dc_yl] + columnofs[dc_x];
  382.  
  383.     // Looks familiar.
  384.     fracstep = dc_iscale; 
  385.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  386.  
  387.     // Looks like an attempt at dithering,
  388.     //  using the colormap #6 (of 0-31, a bit
  389.     //  brighter than average).
  390.     do 
  391.     {
  392.     // Lookup framebuffer, and retrieve
  393.     //  a pixel that is either one column
  394.     //  left or right of the current one.
  395.     // Add index from colormap to index.
  396.     *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]]; 
  397.  
  398.     // Clamp table lookup index.
  399.     if (++fuzzpos == FUZZTABLE) 
  400.         fuzzpos = 0;
  401.     
  402.     dest += SCREENWIDTH;
  403.  
  404.     frac += fracstep; 
  405.     } while (count--); 
  406. #endif
  407.  
  408.   
  409.  
  410.  
  411. #ifndef AMIGA
  412.  
  413. //
  414. // Framebuffer postprocessing.
  415. // Creates a fuzzy image by copying pixels
  416. //  from adjacent ones to left and right.
  417. // Used with an all black colormap, this
  418. //  could create the SHADOW effect,
  419. //  i.e. spectres and invisible players.
  420. //
  421. void R_DrawFuzzColumnLow (void) 
  422.     int            count; 
  423.     byte*        dest; 
  424.     byte*        dest2; 
  425.     fixed_t        frac;
  426.     fixed_t        fracstep;     
  427.  
  428.     // Adjust borders. Low... 
  429.     if (!dc_yl) 
  430.     dc_yl = 1;
  431.  
  432.     // .. and high.
  433.     if (dc_yh == viewheight-1) 
  434.     dc_yh = viewheight - 2; 
  435.          
  436.     count = dc_yh - dc_yl; 
  437.  
  438.     // Zero length.
  439.     if (count < 0) 
  440.     return; 
  441.  
  442.     
  443. #ifdef RANGECHECK 
  444.     if (((unsigned)dc_x << 1) >= SCREENWIDTH
  445.     || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
  446.     {
  447.     I_Error ("R_DrawFuzzColumn: %i to %i at %i",
  448.          dc_yl, dc_yh, dc_x);
  449.     }
  450. #endif
  451.  
  452.  
  453.     // Does not work with blocky mode.
  454.     dest = ylookup[dc_yl] + columnofs[dc_x << 1];
  455.     dest2 = ylookup[dc_yl] + columnofs[(dc_x << 1) + 1];
  456.  
  457.     // Looks familiar.
  458.     fracstep = dc_iscale;
  459.     frac = dc_texturemid + (dc_yl-centery)*fracstep;
  460.  
  461.     // Looks like an attempt at dithering,
  462.     //  using the colormap #6 (of 0-31, a bit
  463.     //  brighter than average).
  464.     do 
  465.     {
  466.     // Lookup framebuffer, and retrieve
  467.     //  a pixel that is either one column
  468.     //  left or right of the current one.
  469.     // Add index from colormap to index.
  470.     *dest2 = *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
  471.  
  472.     // Clamp table lookup index.
  473.     if (++fuzzpos == FUZZTABLE)
  474.         fuzzpos = 0;
  475.  
  476.     dest += SCREENWIDTH;
  477.     dest2 += SCREENWIDTH;
  478.  
  479.     frac += fracstep;
  480.     } while (count--);
  481. }
  482. #endif
  483.  
  484.   
  485.  
  486.  
  487. //
  488. // R_DrawTranslatedColumn
  489. // Used to draw player sprites
  490. //  with the green colorramp mapped to others.
  491. // Could be used with different translation
  492. //  tables, e.g. the lighter colored version
  493. //  of the BaronOfHell, the HellKnight, uses
  494. //  identical sprites, kinda brightened up.
  495. //
  496. byte*    dc_translation;
  497. byte*    translationtables;
  498.  
  499. //#ifndef AMIGA
  500.  
  501. void R_DrawTranslatedColumn (void) 
  502.     int            count; 
  503.     byte*        dest; 
  504.     fixed_t        frac;
  505.     fixed_t        fracstep;     
  506.  
  507.     count = dc_yh - dc_yl; 
  508.     if (count < 0) 
  509.     return; 
  510.                  
  511. #ifdef RANGECHECK 
  512.     if ((unsigned)dc_x >= SCREENWIDTH
  513.     || dc_yl < 0
  514.     || dc_yh >= SCREENHEIGHT)
  515.     {
  516.     I_Error ( "R_DrawColumn: %i to %i at %i",
  517.           dc_yl, dc_yh, dc_x);
  518.     }
  519.     
  520. #endif 
  521.  
  522.  
  523.     // WATCOM VGA specific.
  524.     /* Keep for fixing.
  525.     if (detailshift)
  526.     {
  527.     if (dc_x & 1)
  528.         outp (SC_INDEX+1,12); 
  529.     else
  530.         outp (SC_INDEX+1,3);
  531.     
  532.     dest = destview + dc_yl*80 + (dc_x>>1); 
  533.     }
  534.     else
  535.     {
  536.     outp (SC_INDEX+1,1<<(dc_x&3)); 
  537.  
  538.     dest = destview + dc_yl*80 + (dc_x>>2); 
  539.     }*/
  540.  
  541.     
  542.     // FIXME. As above.
  543.     dest = ylookup[dc_yl] + columnofs[dc_x]; 
  544.  
  545.     // Looks familiar.
  546.     fracstep = dc_iscale; 
  547.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  548.  
  549.     // Here we do an additional index re-mapping.
  550.     do 
  551.     {
  552.     // Translation tables are used
  553.     //  to map certain colorramps to other ones,
  554.     //  used with PLAY sprites.
  555.     // Thus the "green" ramp of the player 0 sprite
  556.     //  is mapped to gray, red, black/indigo. 
  557.     *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
  558.     dest += SCREENWIDTH;
  559.     
  560.     frac += fracstep; 
  561.     } while (count--); 
  562.  
  563. //#endif
  564.  
  565.  
  566.  
  567. //
  568. // R_DrawTranslatedColumn
  569. // Used to draw player sprites
  570. //  with the green colorramp mapped to others.
  571. // Could be used with different translation
  572. //  tables, e.g. the lighter colored version
  573. //  of the BaronOfHell, the HellKnight, uses
  574. //  identical sprites, kinda brightened up.
  575. //
  576. byte*    dc_translation;
  577. byte*    translationtables;
  578.  
  579. //#ifndef AMIGA
  580.  
  581. void R_DrawTranslatedColumnLow (void) 
  582.     int            count; 
  583.     byte*        dest; 
  584.     byte*        dest2;
  585.     fixed_t        frac;
  586.     fixed_t        fracstep;     
  587.  
  588.     count = dc_yh - dc_yl; 
  589.     if (count < 0) 
  590.     return; 
  591.                  
  592. #ifdef RANGECHECK 
  593.     if (((unsigned)dc_x << 1) >= SCREENWIDTH
  594.     || dc_yl < 0
  595.     || dc_yh >= SCREENHEIGHT)
  596.     {
  597.     I_Error ( "R_DrawColumn: %i to %i at %i",
  598.           dc_yl, dc_yh, dc_x);
  599.     }
  600.     
  601. #endif 
  602.  
  603.  
  604.     // FIXME. As above.
  605.     dest = ylookup[dc_yl] + columnofs[dc_x << 1]; 
  606.     dest2 = ylookup[dc_yl] + columnofs[(dc_x << 1) + 1];
  607.  
  608.     // Looks familiar.
  609.     fracstep = dc_iscale; 
  610.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  611.  
  612.     // Here we do an additional index re-mapping.
  613.     do 
  614.     {
  615.     // Translation tables are used
  616.     //  to map certain colorramps to other ones,
  617.     //  used with PLAY sprites.
  618.     // Thus the "green" ramp of the player 0 sprite
  619.     //  is mapped to gray, red, black/indigo. 
  620.     *dest2 = *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
  621.     dest += SCREENWIDTH;
  622.     dest2 += SCREENWIDTH;
  623.     
  624.     frac += fracstep; 
  625.     } while (count--); 
  626.  
  627. //#endif
  628.  
  629.  
  630.  
  631. //
  632. // R_InitTranslationTables
  633. // Creates the translation tables to map
  634. //  the green color ramp to gray, brown, red.
  635. // Assumes a given structure of the PLAYPAL.
  636. // Could be read from a lump instead.
  637. //
  638. void R_InitTranslationTables (void)
  639. {
  640.     int        i;
  641.     
  642.     translationtables = Z_Malloc (256*3+255, PU_STATIC, 0);
  643.     translationtables = (byte *)(( (int)translationtables + 255 )& ~255);
  644.     
  645.     // translate just the 16 green colors
  646.     for (i=0 ; i<256 ; i++)
  647.     {
  648.     if (i >= 0x70 && i<= 0x7f)
  649.     {
  650.         // map green ramp to gray, brown, red
  651.         translationtables[i] = 0x60 + (i&0xf);
  652.         translationtables [i+256] = 0x40 + (i&0xf);
  653.         translationtables [i+512] = 0x20 + (i&0xf);
  654.     }
  655.     else
  656.     {
  657.         // Keep all other colors as is.
  658.         translationtables[i] = translationtables[i+256] 
  659.         = translationtables[i+512] = i;
  660.     }
  661.     }
  662. }
  663.  
  664.  
  665.  
  666.  
  667. //
  668. // R_DrawSpan 
  669. // With DOOM style restrictions on view orientation,
  670. //  the floors and ceilings consist of horizontal slices
  671. //  or spans with constant z depth.
  672. // However, rotation around the world z axis is possible,
  673. //  thus this mapping, while simpler and faster than
  674. //  perspective correct texture mapping, has to traverse
  675. //  the texture at an angle in all but a few cases.
  676. // In consequence, flats are not stored by column (like walls),
  677. //  and the inner loop has to step in texture space u and v.
  678. //
  679. int            ds_y; 
  680. int            ds_x1; 
  681. int            ds_x2;
  682.  
  683. lighttable_t*        ds_colormap; 
  684.  
  685. fixed_t            ds_xfrac; 
  686. fixed_t            ds_yfrac; 
  687. fixed_t            ds_xstep; 
  688. fixed_t            ds_ystep;
  689.  
  690. // start of a 64*64 tile image 
  691. byte*            ds_source;    
  692.  
  693. // just for profiling
  694. int            dscount;
  695.  
  696.  
  697. //
  698. // Draws the actual span.
  699. // UNUSED.
  700. #ifndef AMIGA
  701. void R_DrawSpan (void) 
  702.     fixed_t        xfrac;
  703.     fixed_t        yfrac; 
  704.     byte*        dest; 
  705.     int            count;
  706.     int            spot; 
  707.      
  708. #ifdef RANGECHECK 
  709.     if (ds_x2 < ds_x1
  710.     || ds_x1<0
  711.     || ds_x2>=SCREENWIDTH  
  712.     || (unsigned)ds_y>SCREENHEIGHT)
  713.     {
  714.     I_Error( "R_DrawSpan: %i to %i at %i",
  715.          ds_x1,ds_x2,ds_y);
  716.     }
  717. //    dscount++; 
  718. #endif 
  719.  
  720.     
  721.     xfrac = ds_xfrac; 
  722.     yfrac = ds_yfrac; 
  723.      
  724.     dest = ylookup[ds_y] + columnofs[ds_x1];
  725.  
  726.     // We do not check for zero spans here?
  727.     count = ds_x2 - ds_x1; 
  728.  
  729.     do 
  730.     {
  731.     // Current texture index in u,v.
  732.     spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
  733.  
  734.     // Lookup pixel from flat texture tile,
  735.     //  re-index using light/colormap.
  736.     *dest++ = ds_colormap[ds_source[spot]];
  737.  
  738.     // Next step in u,v.
  739.     xfrac += ds_xstep; 
  740.     yfrac += ds_ystep;
  741.     
  742.     } while (count--); 
  743. #endif
  744.  
  745.  
  746.  
  747. // UNUSED.
  748. // Loop unrolled by 4.
  749. #if 0
  750. void R_DrawSpan (void) 
  751.     unsigned    position, step;
  752.  
  753.     byte*    source;
  754.     byte*    colormap;
  755.     byte*    dest;
  756.     
  757.     unsigned    count;
  758.     usingned    spot; 
  759.     unsigned    value;
  760.     unsigned    temp;
  761.     unsigned    xtemp;
  762.     unsigned    ytemp;
  763.         
  764.     position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff);
  765.     step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff);
  766.         
  767.     source = ds_source;
  768.     colormap = ds_colormap;
  769.     dest = ylookup[ds_y] + columnofs[ds_x1];     
  770.     count = ds_x2 - ds_x1 + 1; 
  771.     
  772.     while (count >= 4) 
  773.     { 
  774.     ytemp = position>>4;
  775.     ytemp = ytemp & 4032;
  776.     xtemp = position>>26;
  777.     spot = xtemp | ytemp;
  778.     position += step;
  779.     dest[0] = colormap[source[spot]]; 
  780.  
  781.     ytemp = position>>4;
  782.     ytemp = ytemp & 4032;
  783.     xtemp = position>>26;
  784.     spot = xtemp | ytemp;
  785.     position += step;
  786.     dest[1] = colormap[source[spot]];
  787.     
  788.     ytemp = position>>4;
  789.     ytemp = ytemp & 4032;
  790.     xtemp = position>>26;
  791.     spot = xtemp | ytemp;
  792.     position += step;
  793.     dest[2] = colormap[source[spot]];
  794.     
  795.     ytemp = position>>4;
  796.     ytemp = ytemp & 4032;
  797.     xtemp = position>>26;
  798.     spot = xtemp | ytemp;
  799.     position += step;
  800.     dest[3] = colormap[source[spot]]; 
  801.         
  802.     count -= 4;
  803.     dest += 4;
  804.     } 
  805.     while (count > 0) 
  806.     { 
  807.     ytemp = position>>4;
  808.     ytemp = ytemp & 4032;
  809.     xtemp = position>>26;
  810.     spot = xtemp | ytemp;
  811.     position += step;
  812.     *dest++ = colormap[source[spot]]; 
  813.     count--;
  814.     } 
  815. #endif
  816.  
  817.  
  818. #ifndef AMIGA
  819. //
  820. // Again..
  821. //
  822. void R_DrawSpanLow (void) 
  823.     fixed_t        xfrac;
  824.     fixed_t        yfrac; 
  825.     byte*        dest; 
  826.     int            count;
  827.     int            spot; 
  828.      
  829. #ifdef RANGECHECK 
  830.     if (ds_x2 < ds_x1
  831.     || ds_x1<0
  832.     || ds_x2>=SCREENWIDTH  
  833.     || (unsigned)ds_y>SCREENHEIGHT)
  834.     {
  835.     I_Error( "R_DrawSpan: %i to %i at %i",
  836.          ds_x1,ds_x2,ds_y);
  837.     }
  838. //    dscount++; 
  839. #endif 
  840.      
  841.     xfrac = ds_xfrac; 
  842.     yfrac = ds_yfrac; 
  843.  
  844.     // Blocky mode, need to multiply by 2.
  845.     ds_x1 <<= 1;
  846.     ds_x2 <<= 1;
  847.     
  848.     dest = ylookup[ds_y] + columnofs[ds_x1];
  849.   
  850.     
  851.     count = ds_x2 - ds_x1; 
  852.     do 
  853.     { 
  854.     spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
  855.     // Lowres/blocky mode does it twice,
  856.     //  while scale is adjusted appropriately.
  857.     *dest++ = ds_colormap[ds_source[spot]]; 
  858.     *dest++ = ds_colormap[ds_source[spot]];
  859.     
  860.     xfrac += ds_xstep; 
  861.     yfrac += ds_ystep; 
  862.  
  863.     } while (count--); 
  864. }
  865. #endif
  866.  
  867. //
  868. // R_InitBuffer 
  869. // Creats lookup tables that avoid
  870. //  multiplies and other hazzles
  871. //  for getting the framebuffer address
  872. //  of a pixel to draw.
  873. //
  874. void
  875. R_InitBuffer
  876. ( int        width,
  877.   int        height ) 
  878.     int        i; 
  879.  
  880.     // Handle resize,
  881.     //  e.g. smaller view windows
  882.     //  with border and/or status bar.
  883.     viewwindowx = (SCREENWIDTH-width) >> 1; 
  884.  
  885.     // Column offset. For windows.
  886.     for (i=0 ; i<width ; i++) 
  887.     columnofs[i] = viewwindowx + i;
  888.  
  889.     // Samw with base row offset.
  890.     if (width == SCREENWIDTH) 
  891.     viewwindowy = 0; 
  892.     else 
  893.     viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1; 
  894.  
  895.     // Preclaculate all row offsets.
  896.     for (i=0 ; i<height ; i++) {
  897.     ylookup[i] = screens[0] + (i+viewwindowy)*SCREENWIDTH; 
  898.         ylookup2[i] = ylookup[i] + viewwindowx;
  899.     }
  900.  
  901.  
  902.  
  903.  
  904. //
  905. // R_FillBackScreen
  906. // Fills the back screen with a pattern
  907. //  for variable screen sizes
  908. // Also draws a beveled edge.
  909. //
  910. void R_FillBackScreen (void) 
  911.     byte*    src;
  912.     byte*    dest; 
  913.     int        x;
  914.     int        y; 
  915.     patch_t*    patch;
  916.  
  917.     // DOOM border patch.
  918.     char    name1[] = "FLOOR7_2";
  919.  
  920.     // DOOM II border patch.
  921.     char    name2[] = "GRNROCK";    
  922.  
  923.     char*    name;
  924.     
  925.     if (scaledviewwidth == 320)
  926.     return;
  927.     
  928.     if ( gamemode == commercial)
  929.     name = name2;
  930.     else
  931.     name = name1;
  932.     
  933.     src = W_CacheLumpName (name, PU_CACHE); 
  934.     dest = screens[1]; 
  935.      
  936.     for (y=0 ; y<SCREENHEIGHT-SBARHEIGHT ; y++) 
  937.     { 
  938.     for (x=0 ; x<SCREENWIDTH/64 ; x++) 
  939.     { 
  940.         memcpy (dest, src+((y&63)<<6), 64); 
  941.         dest += 64; 
  942.     } 
  943.  
  944.     if (SCREENWIDTH&63) 
  945.     { 
  946.         memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63); 
  947.         dest += (SCREENWIDTH&63); 
  948.     } 
  949.     } 
  950.     
  951.     patch = W_CacheLumpName ("brdr_t",PU_CACHE);
  952.  
  953.     for (x=0 ; x<scaledviewwidth ; x+=8)
  954.     V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
  955.     patch = W_CacheLumpName ("brdr_b",PU_CACHE);
  956.  
  957.     for (x=0 ; x<scaledviewwidth ; x+=8)
  958.     V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
  959.     patch = W_CacheLumpName ("brdr_l",PU_CACHE);
  960.  
  961.     for (y=0 ; y<viewheight ; y+=8)
  962.     V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
  963.     patch = W_CacheLumpName ("brdr_r",PU_CACHE);
  964.  
  965.     for (y=0 ; y<viewheight ; y+=8)
  966.     V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
  967.  
  968.  
  969.     // Draw beveled edge. 
  970.     V_DrawPatch (viewwindowx-8,
  971.          viewwindowy-8,
  972.          1,
  973.          W_CacheLumpName ("brdr_tl",PU_CACHE));
  974.     
  975.     V_DrawPatch (viewwindowx+scaledviewwidth,
  976.          viewwindowy-8,
  977.          1,
  978.          W_CacheLumpName ("brdr_tr",PU_CACHE));
  979.     
  980.     V_DrawPatch (viewwindowx-8,
  981.          viewwindowy+viewheight,
  982.          1,
  983.          W_CacheLumpName ("brdr_bl",PU_CACHE));
  984.     
  985.     V_DrawPatch (viewwindowx+scaledviewwidth,
  986.          viewwindowy+viewheight,
  987.          1,
  988.          W_CacheLumpName ("brdr_br",PU_CACHE));
  989.  
  990.  
  991. //
  992. // Copy a screen buffer.
  993. //
  994. void
  995. R_VideoErase
  996. ( unsigned    ofs,
  997.   int        count ) 
  998.   // LFB copy.
  999.   // This might not be a good idea if memcpy
  1000.   //  is not optiomal, e.g. byte by byte on
  1001.   //  a 32bit CPU, as GNU GCC/Linux libc did
  1002.   //  at one point.
  1003.     memcpy (screens[0]+ofs, screens[1]+ofs, count); 
  1004.  
  1005.  
  1006. //
  1007. // R_DrawViewBorder
  1008. // Draws the border around the view
  1009. //  for different size windows?
  1010. //
  1011. void
  1012. V_MarkRect
  1013. ( int        x,
  1014.   int        y,
  1015.   int        width,
  1016.   int        height ); 
  1017.  
  1018. void R_DrawViewBorder (void) 
  1019.     int        top;
  1020.     int        side;
  1021.     int        ofs;
  1022.     int        i; 
  1023.  
  1024.     if (scaledviewwidth == SCREENWIDTH) 
  1025.     return; 
  1026.   
  1027.     top = ((SCREENHEIGHT-SBARHEIGHT)-viewheight)/2; 
  1028.     side = (SCREENWIDTH-scaledviewwidth)/2; 
  1029.  
  1030.     // copy top and one line of left side 
  1031.     R_VideoErase (0, top*SCREENWIDTH+side); 
  1032.  
  1033.     // copy one line of right side and bottom 
  1034.     ofs = (viewheight+top)*SCREENWIDTH-side; 
  1035.     R_VideoErase (ofs, top*SCREENWIDTH+side); 
  1036.  
  1037.     // copy sides using wraparound 
  1038.     ofs = top*SCREENWIDTH + SCREENWIDTH-side; 
  1039.     side <<= 1;
  1040.     
  1041.     for (i=1 ; i<viewheight ; i++) 
  1042.     { 
  1043.     R_VideoErase (ofs, side); 
  1044.     ofs += SCREENWIDTH; 
  1045.     } 
  1046.  
  1047.     // ? 
  1048.     V_MarkRect (0,0,SCREENWIDTH, SCREENHEIGHT-SBARHEIGHT); 
  1049.  
  1050.  
  1051.